#include "constants.h";

XfMissionChapterExecute={
	private ["_chapter_succeeded"];
	diag_log "";
	diag_log "=========================================================================";
	diag_log "                             CHAPTER 4                                   ";
	diag_log "=========================================================================";
	diag_log "";
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterExecute","Starting Chapter","_last_random_reinforcement","_random_reinf_diff","_reinforcement_power"];
	DM_Mission_Chapter_CanRun = True;
	DM_Mission_Chapter_Runs = True;
	DM_Mission_Chapter_Success = 0;
	call XfMissionChapterSetup;
	_chapter_succeeded = false;
	if (!DM_Mission_Mission_CanRun) exitWith {diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterSetup","Mission canceled!"];};
	
	// We need the castle infos to send paras to the right place :)
	_random_town = DM_Chapter_Location;
	_random_town_pos = _random_town select XF_MAP_LOCATION_CENTER;
	_random_town_size = _random_town select XF_MAP_LOCATION_SIZE;
	if (_random_town_size < 200) then { _random_town_size = 200; };
	_building = DM_Target;
	_surrounding_buildings = DM_Target nearObjects ["House",120];
	for [{_i = 0},{_i < count _surrounding_buildings},{_i = _i + 1}] do {
		if ((count ([(_surrounding_buildings select _i),"HIDE", false] call XfBuildingPosArray) <= 0)
		     || (((_surrounding_buildings select _i) distance _building) < 80)) then {_surrounding_buildings set [_i, "XxDeLxX"]};
	};
	_surrounding_buildings = _surrounding_buildings - ["XxDeLxX"];
	
	_camp_branca_pos = DM_Chapter_Position;
	
	_hostage_free = false;
	_hostage_free_updated = false;
	_hostage_safe = false;
	_hostage_safe_updated = false;
	_hostage_alive = true;
	_near_hostage = false;
	_near_hostage_done = false;
	_hostage_died = false;
	
	_player_detected = false;
	_player_decteted_updated = false;
	
	_enemy_initial_count = ([_random_town_pos,350,d_enemy_side] call XfMissionGetZoneSideCount) select 0;
	
	_unique_id = 0;
	_reinforcements = ((call XPlayersNumber) * DM_Mission_RandomReinforcement) max 2;

	diag_log Format["(%1)[%2]: %3: %4: %5, %6",diag_tickTime,"chapter4.sqf","XfMissionChapterExecute","Entering the loop",[_reinforcements, _enemy_initial_count, _surrounding_buildings], Time];
	while {DM_Mission_Chapter_CanRun AND DM_Mission_Mission_CanRun} do {
		sleep 10;
		_enemy_count = ([_random_town_pos,350,d_enemy_side] call XfMissionGetZoneSideCount) select 0;
		
		if (X_MP) then {
			{
				if (isPlayer _x) then {
					if (((vehicle _x) distance (getPos _building)) < 50) then { _near_hostage = true; };
				};
			} foreach playableUnits;
		} else {
			if (((vehicle player) distance (getPos _building)) < 50) then { _near_hostage = true; };
		};
		
		_hostage_safe = ["jip_lead_hostage",false] call XNetGetJIP;
		_hostage_free = ["jip_hostage_free",false] call XNetGetJIP;
		_hostage_alive = ["jip_hostage_alive",true] call XNetGetJIP;
		_player_detected = ["jip_player_detected",false] call XNetGetJIP;

		if (_near_hostage && !_near_hostage_done) then {
			_near_hostage_done = true;
		};

		if (!_hostage_alive && !_hostage_died) then {
			_hostage_died = true;
			"STR_MF_M_HAMMER1_4_ABORT" call XfMissionMessageToAll;
			[false,["chapter4_branca_position",_camp_branca_pos, "ICON", "ColorBlue", [1,1],"Camp Branca",0,"hd_objective","",0.6]] call XfMissionMarker;
			if (!_hostage_free_updated) then {
				["FreeHostage","", "","",[],"Failed"] call XfMissionTask;
			} else {
				["ExtractHostage","", "","",[],"Failed"] call XfMissionTask;
			};
		};
		
		if (_hostage_alive && _hostage_safe && !_hostage_safe_updated) then {
			_hostage_safe_updated = true;
			["ExtractHostage","", "","",[],"Succeeded"] call XfMissionTask;
			_chapter_succeeded = true;
			DM_Mission_Chapter_CanRun = false;
			sleep 10;
		};
		
		if (_hostage_died) then {
			_player_at_base = false;
			if (X_MP) then {
				{
					if (isPlayer _x) then {
						if (((vehicle _x) distance (_camp_branca_pos)) < 50) then { _player_at_base = true; };
					};
				} foreach playableUnits;
			} else {
				if (((vehicle player) distance (_camp_branca_pos)) < 50) then { _player_at_base = true; };
			};
			if (_player_at_base) then {
				_chapter_succeeded = false;
				DM_Mission_Chapter_CanRun = false;
			};
			sleep 10;
		};
		
		if (_hostage_alive && _hostage_free && !_hostage_free_updated) then {
			_hostage_free_updated = true;
			["FreeHostage","", "","",[],"Succeeded"] call XfMissionTask;
			_rescue_updated = true;
			["jip_lead_hostage",false] call XNetSetJIP;
			["jip_hostage_alive",true] call XNetSetJIP;
			
			removeallWeapons DM_VIP;
			[DM_VIP,group DM_VIP,getPos DM_VIP,"LEAD",["STR_MF_M_HAMMER1_4_OFFICERSAFE","STR_MF_M_HAMMER1_4_FAILURE","jip_lead_hostage","jip_hostage_alive",[_camp_branca_pos,[80,80],0,false]],"doStop this; removeAllWeapons this;"] call XfMissionCreateMissionUnit;
			["ExtractHostage","STR_MF_M_HAMMER1_4_TASK_EXTRACT", "STR_MF_M_HAMMER1_4_TASK_EXTRACT_DESC","",[],"Created"] call XfMissionTask;
			[false,["chapter1_branca_dest", _camp_branca_pos, "ICON", "ColorBlue", [1,1],"Camp Branca",0,"hd_end","",0.7]] call XfMissionMarker;
			"STR_MF_M_HAMMER1_4_GETBACK" call XfMissionMessageToAll;
			
			// Generate extra groups if needed
			_minimum_count = 7 * (call XPlayersNumber);
			if (_minimum_count > 30) then { _minimum_count = 30; };
			diag_log Format["(%1)[%2]: %3: %4: %5, %6",diag_tickTime,"chapter4.sqf","XfMissionChapterExecute","Generate Groups",[_minimum_count, _enemy_count, _enemy_initial_count], Time];
			if (_enemy_count < _minimum_count) then {
				_grp_cnt = (ceil ((_minimum_count - _enemy_count) / 7)) max 1;
				_positions = [];
				{
					_positions = [_positions, ([_x,"HIDE", false] call XfBuildingPosArrayASL)] call XfArrayPushStack;
				} foreach _surrounding_buildings;
				
				for [{_i = 0},{_i < _grp_cnt},{_i = _i + 1}] do {
					_i_tries = 10;
					_pos = [];
					while { count _pos <= 0 && _i_tries > 0 } do {
						_pos = (_positions call XfRandomArrayVal);
						_pos_ground = _pos set [2,0];
						{
							if (isPlayer _x) then {
								if (([_x, _pos] call XfDistTo) < 15) exitWith {_pos = [] };
							};
						} foreach playableUnits;
						_i_tries = _i_tries - 1;
					};
					if (count _pos > 0) then {
						// [false,[format["grp_reinf_%1",_i],_pos, "ICON", "ColorBlue", [0.5,0.5],"",0,"mil_dot","",0.6]] call XfMissionMarker;
						_grpSoldiers = [d_enemy_side,[_pos,15],["chapter4_random_town_ups","noveh","aware","buildings"],floor(random(5))] call XfMissionCreateFootmenGroup;
						{
							_x setPosASL _pos;
						} foreach units _grpSoldiers;
						diag_log Format["(%1)[%2]: %3: %4: %5, %6",diag_tickTime,"chapter4.sqf","XfMissionChapterExecute","Generated Group",[_pos, _grpSoldiers], Time];
					};
				};
				sleep 5;
			};
			[getPos _building, d_enemy_side, _random_town_size, [], 20] call XfMissionConvergeUnits;
		};

		if (DM_Mission_Chapter_CanRun && _player_detected && !_player_decteted_updated) then {
			_player_decteted_updated = true;
			_minimum_count = (floor((call XPlayersNumber) / 3) + 1);
			[d_enemy_side,[(getPos _building),100],"VEH",_minimum_count,XF_VEHICLE_TYPES_LIGHTWHEEL] call XfMissionCallReinforcement;
		};

		If (DM_Mission_Chapter_CanRun AND (DM_Mission_RandomReinforcement > 1) AND (_reinforcements > 0) AND !_hostage_died) then {
			// If the player is detected and no reinforcement is on the way.. Then we send new troops in :)
			if ((_enemy_initial_count - _enemy_count) > 5) then {
				if (_unique_id == 0) then {
					// If the reinforcement function returns a value greater than 0, it means a reinforcement was created!
					_unique_id = [d_enemy_side,[_random_town_pos,_random_town_size],"MEN",DM_Mission_RandomReinforcement] call XfMissionCallReinforcement;
					if ((_unique_id) > 0) then {
						diag_log Format["(%1)[%2]: %3: %4: reinf:%5, diff:%6, ini:%7, vec:%8",diag_tickTime,"chapter4.sqf","XfMissionChapterExecute","Sending reinforcement",_reinforcements,_enemy_diff,_enemy_initial_counts];
						_reinforcements = _reinforcements - 1;
					};
				};
			} else {
				_unique_id = 0;
			};
		};
	};
	
	if (DM_Mission_Mission_CanRun) then {
		if (_chapter_succeeded) then {
			call XfMissionChapterSuccess;
		} else {
			call XfMissionChapterFailure;
		};
	} else {
		diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterExecute","Mission canceled!"];
	};
	
	if (!isnil "DM_Ammo_Box") then {
		if (count DM_Ammo_Box == 3) then {
			["d_r_box", [DM_Ammo_Box]] call XNetCallEvent;
		};
	};
	sleep 15;
	_players_found = true;
	_enemy_count = 100;
	While {DM_Mission_Mission_CanRun && _enemy_count > 3 && _players_found} do {
		sleep 5;
		if (X_MP) then {
			_players_found = false;
			{
				if (([(getPos _x), _random_town_pos, _random_town_size * 2] call XfPointInCircle) && isplayer _x) exitWith { _players_found = true; };
			}foreach playableUnits;
		} else {
			_players_found = ([(getPos player), _random_town_pos, _random_town_size * 2] call XfPointInCircle);
		};
		_enemy_count = (([_random_town_pos,400,d_enemy_side] call XfMissionGetZoneSideCount) select 0);
		if (d_mission_debug_messages) then { diag_log Format["(%1)[%2]: %3: %4: player:%5  enemies:%6",diag_tickTime,"chapter4.sqf","XfMissionChapterExecute","Chapter End Check",_players_found,_enemy_count]; };
	};
	// Just in case a reinforcement is already on the way.
	call XfMissionCancelReinforcement;
	call XfMissionChapterCleanUp;
	DM_Mission_Chapter_Runs = False;
};

XfMissionChapterSetup={
	private ["_random_town","_random_town_pos","_random_town_size","_troops_power","_troops_coeff","_grpSpecOps","_i"];
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterSetup","Starting Initialization"];
	
	_branca_ammo = [15633.4,17345.8,0];
	
	_random_town = [];
	_random_town_pos = [];
	_random_town_size = 200;
	_building = objNull;
	_i_tries = 30;

	[["%1\n\n%2","STR_MF_M_HAMMER1_4_NAME","STR_MF_M_HAMMER1_4_INTRO"],([18,00] call XfMissionGetDate),8,10,"PLAIN"] call XfMissionDisplayScreen;	
	sleep 3;
	DM_Ammo_Box = _branca_ammo;
	["d_m_box", [DM_Ammo_Box, (nearestObject [DM_Ammo_Box, "AllVehicles"]), "", d_own_side,"USVehicleBox_EP1"]] call XNetCallEvent;

	// Destination camp branca
	_parameters = [d_map_locations];
	_parameters set [count _parameters, [XF_MAP_LOCATION_UNIQUENAME,"==","CampBranca"]];
	_eligible_towns = _parameters call XfTableFilter;
	if ((count _eligible_towns) <= 0) exitWith {"STR_MF_RANDOMSITEFAILED" call XfMissionMessageToAll; DM_Mission_Mission_CanRun = false; DM_Mission_Chapter_CanRun = false;};
	_camp_branca = _eligible_towns select 0;
	_camp_branca_pos = _camp_branca select XF_MAP_LOCATION_CENTER;
	_camp_branca_size = _camp_branca select XF_MAP_LOCATION_SIZE;
	_camp_branca_name = _camp_branca select XF_MAP_LOCATION_DISPLAYNAME;

	_building_list = [6,-1,1] call XfBuildingFilteredList;
	_town_search_center = [17399.4,18114.1,0];
	_towns = [_town_search_center,1000, true] call XfMissionGetTownsInRange;

	while { count _random_town <= 0 && _i_tries > 0 } do {
		// Only big towns
		_random_town = _towns call XfRandomArrayVal;
		_random_town_pos = _random_town select XF_MAP_LOCATION_CENTER;
		_random_town_size = _random_town select XF_MAP_LOCATION_SIZE;
		_building = objNull;
		_matching_buildings = [];
		
		_objects = nearestObjects [_random_town_pos, _building_list, _random_town_size];
		if (isnull _building && (count _objects > 0)) then {
			{
				_surrounding_count = 0;
				_bld = _x;
				_pos_bld = getPos _bld;
				if (damage _bld < 0.2) then {
					_surrounding_buildings = _pos_bld nearObjects ["House",120];
					{
						if (_x != _bld) then {
							if ((count ([_x,"HIDE", false] call XfBuildingPosArrayASL) > 0) && ((_x distance _pos_bld) < 80)) then { _surrounding_count = _surrounding_count + 1; };
						};
					} foreach _surrounding_buildings;
					if (_surrounding_count > 3) then {
						_matching_buildings set [count _matching_buildings, _bld];
					};
				} else {
					diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterSetup",Format["Ignoring destroyed building in %1", (_random_town select XF_MAP_LOCATION_DISPLAYNAME)]];
				};
			} foreach _objects;
		};
		diag_log Format["(%1)[%2]: %3; %4: %5",diag_tickTime,"chapter4.sqf","XfMissionChapterSetup","Matching buildings", _matching_buildings];
		if (count _matching_buildings > 0) exitWith {
			_building = _matching_buildings call XfRandomArrayVal;
		};
		if (!isnull _building) exitWith {};
		_random_town = [];
		_i_tries = _i_tries - 1;
	};
	if ((count _random_town) <= 0) exitWith {"STR_MF_RANDOMSITEFAILED" call XfMissionMessageToAll; DM_Mission_Mission_CanRun = false; DM_Mission_Chapter_CanRun = false;};
	if (isNull _building) exitWith {"STR_MF_RANDOMBUILDINGFAILED" call XfMissionMessageToAll; DM_Mission_Mission_CanRun = false; DM_Mission_Chapter_CanRun = false;};
	_random_town_name = _random_town select XF_MAP_LOCATION_DISPLAYNAME;
	DM_Chapter_Location = _random_town;
	DM_Chapter_Position = _camp_branca_pos;
	DM_Target = _building;
	
	if (_random_town_size < 200) then { _random_town_size = 200; };
	// UPSMON Marker
	[true,["chapter4_random_town_ups", _random_town_pos, "ELLIPSE", "ColorRed", [_random_town_size,_random_town_size],"",0,"","BDiagonal",0.5]] call XfMissionMarker;
	[true,["chapter4_random_town_ups_building",(getPos _building), "ELLIPSE", "ColorRed", [90,90],"",0,"","FDiagonal",0.5]] call XfMissionMarker;
	[true,["chapter4_random_town_ups_building_big",(getPos _building), "ELLIPSE", "ColorRed", [200,200],"",0,"","FDiagonal",0.5]] call XfMissionMarker;

	// This indicates where the mission takes place
	[_random_town_pos,_random_town_size,_random_town_name] call XfMissionCurrentPosition;

	// If no spot found, we get back an empty position.
	if (count (_teleporter select 0) > 0) then {
		[false,["chapter4_start_position",(_teleporter select 0), "ICON", "ColorBlue", [1,1],"",(_teleporter select 1),"hd_start","",1]] call XfMissionMarker;
	};

	["jip_hostage_free",false] call XNetSetJIP;
	["jip_hostage_alive",true] call XNetSetJIP;
	["jip_lead_hostage",false] call XNetSetJIP;
	_hostage_position = [];
	
	_building_pos_hiding = [_building,"HIDE", false] call XfBuildingPosArrayASL;
	_building_pos_all = [_building,"INTERN", false] call XfBuildingPosArrayASL;
	// We create the bomb
	_filtered_pos = +_building_pos_hiding;
	// We try to filter out the ground positions to force players to go upstairs
	for [{_i = 0},{_i < count _filtered_pos},{_i = _i + 1}] do {
		_hiding_pos = _filtered_pos select _i;
		if ((_hiding_pos select 2) < 2) then {_filtered_pos set [_i, "XxDeLxX"]};
	};
	_filtered_pos = _filtered_pos - ["XxDeLxX"];
	// It's possible we had only ground positions, in such a case we will use them.
	if (count _filtered_pos > 0) then {
		_hostage_position = _filtered_pos call XfRandomArrayVal;
	} else {
		_hostage_position = _building_pos_hiding call XfRandomArrayVal;
	};
	// We don't want to place units ON the hostage :)
	for [{_i = 0},{_i < count _building_pos_all},{_i = _i + 1}] do {
		if (((_building_pos_all select _i) distance _hostage_position) < 1) then { _building_pos_all set [_i, "XxDeLxX"] };
	};
	_building_pos_all = _building_pos_all - ["XxDeLxX"];

	_grp = [d_own_side] call x_creategroup;
	DM_VIP = ["US_Soldier_Officer_EP1",_grp,_hostage_position,"RESCUE",["STR_MF_HOSTAGEFREE","STR_MF_M_HAMMER1_4_FAILURE","jip_hostage_free","jip_hostage_alive"],"doStop this;"] call XfMissionCreateMissionUnit;
	DM_VIP setPosASL _hostage_position;
	removeallWeapons DM_VIP;
	
	diag_log Format["(%1)[%2]: %3; %4: %5",diag_tickTime,"chapter4.sqf","XfMissionChapterSetup","Hostage Position",_hostage_position];
	
	_fnc_KeepInPlace = {
		_unit = _this select 0;
		_unit setUnitPos "Middle";
		_initial_pos = getPos _unit;
		doStop _unit;
		while { alive _unit } do {
			if ((_unit distance _initial_pos) > 2) then { _unit doMove _initial_pos; };
			sleep 1.23456;
		};
	};
	
	_grp_cnt = floor(2 + DM_Mission_EnemyPower);
	for [{_i = 0},{_i < _grp_cnt},{_i = _i + 1}] do {
		_grpSoldiers = [d_enemy_side,[(getPos _building),20],["chapter4_random_town_ups","noveh","aware","buildings","fortify"],floor(random(5))] call XfMissionCreateFootmenGroup;
		{
			if (count _building_pos_all > 0) then {
				_idx = (_building_pos_all call XfRandomFloorArray);
				_pos = _building_pos_all select _idx;
				_building_pos_all set [_idx, "XxDeLxX"];
				_building_pos_all = _building_pos_all - ["XxDeLxX"];
				_x setPosASL _pos;
				_x addEventHandler ["HandleDamage",{_dmg = _this select 2; { _x enableAI "MOVE"; } foreach (units (group (_this select 0)));  _dmg;}];
				[_x] spawn _fnc_KeepInPlace;
			} else {
				_pos = (getPos _building) findEmptyPosition [20, 80];
				if (count _pos > 0) then { _x setPos _pos; };
			};
		} foreach units _grpSoldiers;
	};
	_grpSoldiers = [d_enemy_side,[(getPos _building),80],["chapter4_random_town_ups_building","noveh","aware","buildings"],XF_UNIT_TYPES_SPECIAL_FORCE] call XfMissionCreateFootmenGroup;

	_grp_cnt = 1 + floor((call XPlayersNumber) / 7) + floor(DM_Mission_EnemyPower + DM_Mission_EnemyCoeff);
	for [{_i = 0},{_i < _grp_cnt},{_i = _i + 1}] do {
		_ups_zone = "chapter4_random_town_ups";
		if (random(1) >= 0.5) then { _ups_zone = "chapter4_random_town_ups_building_big"; };
		_grpSoldiers = [d_enemy_side,[getMarkerPos _ups_zone,(getMarkerSize _ups_zone) select 0],[_ups_zone,"noveh","safe","buildings"],floor(random(5))] call XfMissionCreateFootmenGroup;
	};
	
	// The marker which indicates the buildings zone
	[false,["chapter4_random_town_zone", _random_town_pos, "ELLIPSE", "ColorRed", [_random_town_size,_random_town_size],"",0,"","BDiagonal",0.5]] call XfMissionMarker;
	[false,["chapter4_building_position",getPos _building, "ICON", "ColorRed", [1,1],"STR_MF_PRISONER",0,"hd_objective","",0.6]] call XfMissionMarker;
	
	["FreeHostage","STR_MF_M_HAMMER1_4_TASK_FREE", ["STR_MF_M_HAMMER1_4_TASK_FREE_DESC",_random_town_name],"",[],"Created"] call XfMissionTask;
	
	["jip_player_detected",false] call XNetSetJIP;
	[(getPos _building),100,d_own_side,d_enemy_side,"jip_player_detected"] call XfMissionSideDetected;
	
	// This will create air support automatically if selected in the mission setup
	[d_enemy_side,[_random_town_pos,750],DM_Mission_AirSupport] call XfMissionCallAirSupport;
	
	if (typename DM_Mission_Snipers == typename []) then {
		DM_Mission_Snipers set [0, (DM_Mission_Snipers select 0) + 3];
		DM_Mission_Snipers set [1, (DM_Mission_Snipers select 1) + 3];
	} else {
		DM_Mission_Snipers = DM_Mission_Snipers + 3;
	};
	// This will create snipers automatically if selected in the mission setup
	[d_enemy_side,[_random_town_pos,_random_town_size],DM_Mission_Snipers] call XfMissionCreateSnipersArea;
	
	DM_VIP setPosASL _hostage_position;
	
	_amount = round(random(_random_town_size / 14)) + round(_random_town_size / 17);
	[[_random_town_pos,_random_town_size],"CIV",_amount] call XfMissionCivilianSpawn;
};

XfMissionChapterSuccess={
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterSuccess","Starting"];
	"STR_MF_M_HAMMER1_4_SUCCESS" call XfMissionMessageToAll;
	DM_Mission_Chapter_Success = 1;
};

XfMissionChapterFailure={
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterFailure","Starting"];
	DM_Mission_Chapter_Success = -1;
};

// Self-explanatory
XfMissionChapterCleanUp={
	diag_log Format["(%1)[%2]: %3; %4",diag_tickTime,"chapter4.sqf","XfMissionChapterCleanUp","Starting"];
	// Giving an empty position places the teleporter back to the hangar, closing the hangar.
	[[],0] call XfMissionPlaceStartTeleporter;
	[] call XfMissionCleanMarkers;
	[] call XfMissionCleanTriggers;
	[] call XfMissionCleanTasks;
};

DM_Mission_Chapter_Compiled = true;